#ifndef _TIMER_HPP_
#define _TIMER_HPP_

#include <functional>
#include <list>
#include <set>
#include <algorithm>
#include <chrono>
using namespace std::chrono;

// 获取当前时间戳(毫秒)
static time_t getNowInMilliSec()
{
	return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();
}

//第一个参数是指向time_type的指针，第二个参数是用户传递给回调函数的指针
typedef std::function<void(void*,void*)> time_callback;

class Timer
{
private:
	//事件容器中值的类型
	struct time_type
	{
		time_t expire;         //过期的时间戳
		time_t time;           //注册的毫秒
		time_callback cb;      //回调函数
		void *ctx;		       //回调函数参数
	};
public:
	Timer()
	{

	}
	~Timer()
	{

	}

	//获得multimap距现在最快发生的时间事件的时间
	time_t getTime()
	{
		if (_contain.size() > 0)
		{
			auto time = _contain.begin()->first - getNowInMilliSec();
			return time >= 0 ? time : 0;
		}
		else
		{
			return 1000;
		}
	}

	//time的单位是毫秒
	//注册定时事件
	void register_time_event(time_t time, time_callback cb, void *ctx)
	{
		time_type *tmp = new time_type;
		tmp->cb = cb;
		tmp->ctx = ctx;
		tmp->time = time;
		auto expire = time + getNowInMilliSec();
		tmp->expire = expire;
		auto pair = std::make_pair(expire, tmp);
		_contain.insert(pair);
	}

	//注册定时事件
	void register_time_event(time_t time, time_type *val)
	{
		auto tmp = new time_type();
		tmp->time = time;
		auto expire = time + getNowInMilliSec();
		tmp->expire = expire;
		auto pair = std::make_pair(expire, tmp);
		_contain.insert(pair);
	}

	//取消注册定时事件
	void unregister_time_event(void *tType)
	{
		time_type *t = (time_type*)tType;
		auto iter = _contain.find(t->expire);
		if (iter != _contain.end())
		{// 进行更新
			auto ins = (*iter).second;
			delete ins;
			_contain.erase(iter);
		}
	}

	//更新定时事件的时间
	void update_time_event(time_t newTime, void *tType)
	{
		time_type *t = (time_type*)tType;
		auto iter = _contain.find(t->expire);
		if (iter != _contain.end())
		{// 进行更新
			register_time_event(newTime, t->cb, t->ctx);
		}
	}

	void process_timer()
	{
		time_t cur_time = getNowInMilliSec();
		if (_contain.size() > 0)
		{
			for (auto iter = _contain.begin(); iter != _contain.end(); )
			{
				auto ins = (*iter).second;
				if (cur_time >= (*iter).first)
				{// 如果到时间了
					ins->cb(ins, ins->ctx);
					delete ins;
					iter = _contain.erase(iter);
				}
				else
				{
					break;
				}
			}
		}
	}
private:
	//时间模块
	time_t _timer = 0;
	//存放键为时间值为回调函数的容器
	//键：过期事件 值: value_type指针
	std::multimap<time_t, time_type*> _contain;
};

#endif //_TIMER_HPP_
